package view;

import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;

import model.environmentConfig.*;
import controller.*;

public class AttributesPanel extends JPanel implements TreeSelectionListener, FocusListener{
	private JLabel title;
	private JSplitPane splitPane;
	private JScrollPane treeScrollPane, attributesScrollPane;
	List<Component> panels;
	private JTree tree;
	private String focused, unfocused;
	
	public AttributesPanel(){
		title = null;
		splitPane = null;
		treeScrollPane = attributesScrollPane = null;
		panels = null;
		tree = null;
		setupAttributesPanel();
	}
	
	public void setupAttributesPanel(){
		this.removeAll();
		this.setLayout(new BorderLayout(10, 10));
		//this.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));
		 title = new JLabel("Navigator");
		this.add(title, BorderLayout.PAGE_START);
		
		EnvironmentConfiguration eC = ConnectionTester.getEnvironmentConfig();
		if(eC != null){
			//Setup treeScrollPane
			tree = createEnvConfigTree(eC);
			tree.addTreeSelectionListener(this);
			treeScrollPane = new JScrollPane(
					tree,
					JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, 
					JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
			
			//attributesScrollPane
			if(ConnectionTester.getEnvironmentConfig().getSelectedObj() instanceof Node){
				attributesScrollPane = newAttributesScrollPane((Node)(ConnectionTester.getEnvironmentConfig().getSelectedObj()));
			}
			else if(ConnectionTester.getEnvironmentConfig().getSelectedObj() instanceof CommunicationChannel){
				attributesScrollPane = newAttributesScrollPane((CommunicationChannel)(ConnectionTester.getEnvironmentConfig().getSelectedObj()));
			}
			else
				attributesScrollPane = newAttributesScrollPane(ConnectionTester.getEnvironmentConfig());
			
			Dimension minimumSize = new Dimension(100, 70);
			treeScrollPane.setMinimumSize(minimumSize);
						
	        splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
			splitPane.setTopComponent(treeScrollPane);
			splitPane.setBottomComponent(attributesScrollPane);
			splitPane.setDividerLocation(200);
			add(splitPane, BorderLayout.CENTER);
		}
		else{
			//no EnvironmentConfig Loaded
			add(new JLabel("No Configuration Loaded"), BorderLayout.PAGE_START);
		}
	}
	
	public JTree createEnvConfigTree(EnvironmentConfiguration eC){
		//create tree from eC
		String rootName = "Environment Configuration"; 
		//TODO rootName = eC.getName();
		DefaultMutableTreeNode top = new DefaultMutableTreeNode(rootName);
		createTreeNodes(top, eC);
		
		JTree tree = new JTree(top);
		tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
		
		return tree;
	}
	
	private void createTreeNodes(DefaultMutableTreeNode top, EnvironmentConfiguration eC) {
		DefaultMutableTreeNode nodes = null;
        DefaultMutableTreeNode channels = null;
        
        nodes = new DefaultMutableTreeNode("Nodes");
        channels = new DefaultMutableTreeNode("Channels");
        if(eC != null){
	        for(Node n:eC.getNodes().values()){
	        	DefaultMutableTreeNode node = new DefaultMutableTreeNode(n);
	        	nodes.add(node);
	        }
	        for(CommunicationChannel c:eC.getChannels()){
	        	DefaultMutableTreeNode channel = new DefaultMutableTreeNode(c);
	        	channels.add(channel);
	        }
        }
		top.add(nodes);
		top.add(channels);
	}
	
	public void valueChanged(TreeSelectionEvent e) {
		DefaultMutableTreeNode treeNode =  (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
		if(treeNode != null){
			if(treeNode.isRoot()){
				EnvironmentConfiguration eC = ConnectionTester.getEnvironmentConfig();
				if(splitPane == null){
					setupAttributesPanel();
				}
				splitPane.remove(splitPane.getBottomComponent());
				attributesScrollPane = newAttributesScrollPane(eC);
				splitPane.setBottomComponent(attributesScrollPane);
				splitPane.setDividerLocation(200);
			}
			else if(treeNode.isLeaf()){
				//determine Leaf type
				Object obj = treeNode.getUserObject();
				attributesScrollPane.removeAll();
				if(obj instanceof Node){
					ConnectionTester.setSelected((Node)obj);
					attributesScrollPane = newAttributesScrollPane((Node)obj);					
				}
				else if(obj instanceof CommunicationChannel){
					ConnectionTester.setSelected((CommunicationChannel)obj);
					attributesScrollPane = newAttributesScrollPane((CommunicationChannel)obj);
				}
				splitPane.remove(splitPane.getBottomComponent());
				splitPane.setBottomComponent(attributesScrollPane);
				splitPane.setDividerLocation(200);
			}
			MainFrame.refresh();
		}
	}
	
	public JScrollPane newAttributesScrollPane(EnvironmentConfiguration eC){
		panels = new ArrayList<Component>();
		if(eC != null){
			JTextField numNodes = new JTextField(((Integer) eC.getNodes().size()).toString());
			JTextField numChans = new JTextField(((Integer) eC.getChannels().size()).toString());
			addToPanels(panels, new JLabel("Nodes:"), numNodes);
			addToPanels(panels, new JLabel("Channels:"), numChans);
			numNodes.setEditable(false);
			numNodes.removeFocusListener(this);
			numChans.setEditable(false);
			numChans.removeFocusListener(this);
		}
		else{
			JTextField numNodes = new JTextField();
			JTextField numChans = new JTextField();
			addToPanels(panels, new JLabel("Nodes:"), numNodes);
			addToPanels(panels, new JLabel("Channels:"), numChans);
			numNodes.setEditable(false);
			numNodes.removeFocusListener(this);
			numChans.setEditable(false);
			numChans.removeFocusListener(this);
		}
		
		JPanel panel = new JPanel(new GridLayout(panels.size(), 1));
		for(Component p:panels){
			panel.add(p);
		}
		JScrollPane pane = new JScrollPane(
				panel,
				JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
				JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		Dimension minimumSize = new Dimension(175, 70);
		pane.setMinimumSize(minimumSize);
		return pane;
	}
	
	public JScrollPane newAttributesScrollPane(Node n){
		panels = new ArrayList<Component>();
		Boolean editable = (ConnectionTester.getMode() == Mode.DESIGNER);
		if(n != null){
			panels.add(new JLabel("Node Info"));
			//computerName
			addToPanels(panels, new JLabel("Computer Name:"), new ECTextField(n.getComputerName(), n, Attribute.COMPUTER_NAME, editable));
			//operating system
			addToPanels(panels, new JLabel("Operating System:"), new ECTextField(n.getOperatingSystem(), n, Attribute.OS, editable));
			//external IP
			addToPanels(panels, new JLabel("ExternalIP Address:"), new ECTextField(n.getExternalIPAddress(), n, Attribute.EXT_IP, editable));
			//internal IP
			addToPanels(panels, new JLabel("InternalIP Address:"), new ECTextField(n.getInternalIPAddress(), n, Attribute.INT_IP, editable));

			//softwarePackages
			panels.add(new JLabel("Software Packages"));
			int s = 1;
			for(SoftwarePackage sP:n.getRequiredSoftwarePackages()){
				panels.add(new JLabel("Package " + s));
				//name
				addToPanels(panels, new JLabel(" Name:"), new ECTextField(sP.getName(), sP, Attribute.PACKAGE_NAME, editable));
				//version
				addToPanels(panels, new JLabel(" Version:"), new ECTextField(sP.getVersion(), sP, Attribute.PACKAGE_VERSION, editable));
				s++;
			}
			//securityZones
			panels.add(new JLabel("Security Zones"));
			int z = 1;
			for(SecurityZone sZ:n.getSecurityZone()){
				panels.add(new JLabel("Zone " + z));
				//name
				addToPanels(panels, new JLabel(" Name:"), new ECTextField(sZ.getName(), sZ, Attribute.SECURITYZONE_NAME, editable));
				z++;
			}
			//organizations
			panels.add(new JLabel("Organizations"));
			int g = 1;
			for(Organization o:n.getResponsibleOrganization()){
				panels.add(new JLabel("Organization " + g));
				//name
				addToPanels(panels, new JLabel(" Name:"), new ECTextField(o.getName(), o, Attribute.ORGANIZATION_NAME, editable));
				g++;
			}
			//contactPerson
			panels.add(new JLabel("ContactPersons"));
			int c = 1;
			for(ContactPerson cP:n.getContactPerson()){
				panels.add(new JLabel("Person " + c));
				//name
				addToPanels(panels, new JLabel(" Name:"), new ECTextField(cP.getName(), cP, Attribute.CONTACTPERSON_NAME , editable));
				//phoneNumber
				addToPanels(panels, new JLabel(" Phone:"), new ECTextField(cP.getPhoneNumber(), cP, Attribute.CONTACTPERSON_PHONE, editable));
				//email
				addToPanels(panels, new JLabel(" Email:"), new ECTextField(cP.getEmail(), cP, Attribute.CONTACTPERSON_EMAIL, editable));
				c++;
			}	
		}
		else{
			panels.add(new JLabel("Node Info"));
			//computerName
			addToPanels(panels, new JLabel("Computer Name:"), new ECTextField(n, Attribute.COMPUTER_NAME, editable));
			//operating system
			addToPanels(panels, new JLabel("Operating System:"), new ECTextField(n, Attribute.OS, editable));
			//external IP
			addToPanels(panels, new JLabel("ExternalIP Address:"), new ECTextField(n, Attribute.EXT_IP, editable));
			//internal IP
			addToPanels(panels, new JLabel("InternalIP Address:"), new ECTextField(n, Attribute.INT_IP, editable));

			//softwarePackages
			panels.add(new JLabel("Software Packages"));
			int s = 1;
			for(SoftwarePackage sP:n.getRequiredSoftwarePackages()){
				panels.add(new JLabel("Package " + s));
				//name
				addToPanels(panels, new JLabel(" Name:"), new ECTextField(sP, Attribute.PACKAGE_NAME, editable));
				//version
				addToPanels(panels, new JLabel(" Version:"), new ECTextField(sP, Attribute.PACKAGE_VERSION, editable));
				s++;
			}
			//securityZones
			panels.add(new JLabel("Security Zones"));
			int z = 1;
			for(SecurityZone sZ:n.getSecurityZone()){
				panels.add(new JLabel("Zone " + z));
				//name
				addToPanels(panels, new JLabel(" Name:"), new ECTextField(sZ, Attribute.SECURITYZONE_NAME, editable));
				z++;
			}
			//organizations
			panels.add(new JLabel("Organizations"));
			int g = 1;
			for(Organization o:n.getResponsibleOrganization()){
				panels.add(new JLabel("Organization " + g));
				//name
				addToPanels(panels, new JLabel(" Name:"), new ECTextField(o, Attribute.ORGANIZATION_NAME, editable));
				g++;
			}
			//contactPerson
			panels.add(new JLabel("ContactPersons"));
			int c = 1;
			for(ContactPerson cP:n.getContactPerson()){
				panels.add(new JLabel("Person " + c));
				//name
				addToPanels(panels, new JLabel(" Name:"), new ECTextField(cP, Attribute.CONTACTPERSON_NAME , editable));
				//phoneNumber
				addToPanels(panels, new JLabel(" Phone:"), new ECTextField(cP, Attribute.CONTACTPERSON_PHONE, editable));
				//email
				addToPanels(panels, new JLabel(" Email:"), new ECTextField(cP, Attribute.CONTACTPERSON_EMAIL, editable));
				c++;
			}
		}
		JPanel panel = new JPanel(new GridLayout(panels.size(), 1));
		for(Component p:panels){
			panel.add(p);
		}
		JScrollPane pane = new JScrollPane(
				panel,
				JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
				JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		Dimension minimumSize = new Dimension(175, 70);
		pane.setMinimumSize(minimumSize);
		return pane;
	}
	
	private void addToPanels(List<Component> panels, Component l, Component t){
		JPanel tempPanel = new JPanel();
		tempPanel.add(l);
		t.addFocusListener(this);
		tempPanel.add(t);
		panels.add(tempPanel);
	}
	
	public JScrollPane newAttributesScrollPane(CommunicationChannel c){
		panels = new ArrayList<Component>();
		Boolean editable = (ConnectionTester.getMode() == Mode.DESIGNER);
		if(c != null){
			//initiatorNode
			addToPanels(panels, new JLabel("Initiator Node:"), new ECTextField(c.getInitiatorNode().toString(), c, Attribute.INIT_NODE, editable));
			//listeningNode
			addToPanels(panels, new JLabel("Listening Node:"), new ECTextField(c.getListeningNode().toString(), c, Attribute.LIST_NODE, editable));
			//transportProtocol
			if(c.getTransportProtocol() != null)
				addToPanels(panels, new JLabel("Transport Protocol:"), new ECTextField(c.getTransportProtocol().getName(), c, Attribute.TRANS_PROTOCOL, editable));
			//applicationProtocol 
			if(c.getApplicationProtocol() != null)
				addToPanels(panels, new JLabel("Application Protocol:"), new ECTextField(c.getApplicationProtocol().getName(), c, Attribute.APP_PROTOCOL, editable));
			//initiatorPortRangeStart
			int start = c.getInitiatorPortRange()[0];
			addToPanels(panels, new JLabel("Initiator Port Range Start:"), new ECTextField(((Integer)start).toString(), c, Attribute.INIT_PORTRANGE_START, editable));
			//initiatorPortRangeEnd 
			int end = c.getInitiatorPortRange()[1];
			addToPanels(panels, new JLabel("Initiator Port Range End:"), new ECTextField(((Integer)end).toString(), c, Attribute.INIT_PORTRANGE_END, editable));
			
			//listenerPortRangeStart
			start = c.getListenerPortRange()[0];
			addToPanels(panels, new JLabel("Listener Port Range Start:"), new ECTextField(((Integer)start).toString(), c, Attribute.LIST_PORTRANGE_START, editable));
			//listenerPortRangeEnd 
			end = c.getListenerPortRange()[1];
			addToPanels(panels, new JLabel("Listener Port Range End:"), new ECTextField(((Integer)end).toString(), c, Attribute.LIST_PORTRANGE_END, editable));
		}
		else{
			//initiatorNode
			addToPanels(panels, new JLabel("Initiator Node:"), new ECTextField(c, Attribute.INIT_NODE, editable));
			//listeningNode
			addToPanels(panels, new JLabel("Listening Node:"), new ECTextField(c, Attribute.LIST_NODE, editable));
			//transportProtocol
			if(c.getTransportProtocol() != null)
				addToPanels(panels, new JLabel("Transport Protocol:"), new ECTextField(c, Attribute.TRANS_PROTOCOL, editable));
			//applicationProtocol 
			if(c.getApplicationProtocol() != null)
				addToPanels(panels, new JLabel("Application Protocol:"), new ECTextField(c, Attribute.APP_PROTOCOL, editable));
			//initiatorPortRangeStart
			int start = c.getInitiatorPortRange()[0];
			addToPanels(panels, new JLabel("Initiator Port Range Start:"), new ECTextField(c, Attribute.INIT_PORTRANGE_START, editable));
			//initiatorPortRangeEnd 
			int end = c.getInitiatorPortRange()[1];
			addToPanels(panels, new JLabel("Initiator Port Range End:"), new ECTextField(c, Attribute.INIT_PORTRANGE_END, editable));
			
			//listenerPortRangeStart
			start = c.getListenerPortRange()[0];
			addToPanels(panels, new JLabel("Listener Port Range Start:"), new ECTextField(c, Attribute.LIST_PORTRANGE_START, editable));
			//listenerPortRangeEnd 
			end = c.getListenerPortRange()[1];
			addToPanels(panels, new JLabel("Listener Port Range End:"), new ECTextField(c, Attribute.LIST_PORTRANGE_END, editable));
		}
		
		JPanel panel = new JPanel(new GridLayout(panels.size(), 1));
		for(Component p:panels){
			panel.add(p);
		}
		JScrollPane pane = new JScrollPane(
				panel,
				JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
				JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		Dimension minimumSize = new Dimension(175, 70);
		pane.setMinimumSize(minimumSize);
		return pane;
	}
	
	public void focusGained(FocusEvent e) {
		// TODO Auto-generated method stub
		focused = ((JTextField) e.getComponent()).getText();
		System.out.println("focused on: " + focused);
		//((JTextField) e.getComponent()).get
	}

	public void focusLost(FocusEvent e) {
		// TODO Auto-generated method stub
		unfocused = ((JTextField)e.getComponent()).getText();
		((ECTextField)e.getComponent()).setECValue(unfocused);
		System.out.println("lost focus on: " + unfocused);
	}
	
	
	private class ECTextField extends JTextField{
		private String text;
		private Object obj;
		private Attribute attr;
		
		public ECTextField(String str, Object obj, Attribute attr, Boolean editable){
			super(str);
			this.text = str;
			this.obj = obj;
			this.attr = attr;
			this.setPreferredSize(new Dimension(100,18));
			this.setEditable(editable);
		}
		
		public ECTextField(Object obj, Attribute attr, Boolean editable){
			super();
			this.text = "";
			this.obj = obj;
			this.attr = attr;
			this.setPreferredSize(new Dimension(100,18));
			this.setEditable(editable);
		}
		
		public void setECValue(String str){
			if(obj instanceof Node){
				Node n = (Node)obj;
				if(n != null){
					switch(attr) {
					case COMPUTER_NAME:
						n.setComputerName(str);
						break;
					case OS:
						n.setOperatingSystem(str);
						break;
					case EXT_IP:
						n.setExternalIPAddress(str);
						break;
					case INT_IP:
						n.setInternalIPAddress(str);
						break;
					}
				}
			}
			else if(obj instanceof SoftwarePackage){
				SoftwarePackage sP = (SoftwarePackage)obj;
				if(sP != null){
				switch(attr){
					case PACKAGE_NAME:
						sP.setName(str);
						break;
					case PACKAGE_VERSION:
						sP.setVersion(str);
						break;
					}
				}
			}
			else if(obj instanceof SecurityZone){
				SecurityZone sZ = (SecurityZone)obj;
				if(sZ != null){
					switch(attr){
						case SECURITYZONE_NAME:
							sZ.setName(str);
							break;
					}
				}
			}
			else if(obj instanceof Organization){
				Organization o = (Organization)obj;
				if(o != null){
					switch(attr){
						case ORGANIZATION_NAME:
							o.setName(str);
							break;
					}
				}
			}
			else if(obj instanceof ContactPerson){
				ContactPerson cP = (ContactPerson)obj;
				if(cP != null){
					switch(attr){
						case CONTACTPERSON_NAME:
							cP.setName(str);
							break;
						case CONTACTPERSON_PHONE:
							cP.setPhoneNumber(str);
							break;
						case CONTACTPERSON_EMAIL:
							cP.setEmail(str);
							break;
					}
				}
			}
			else if(obj instanceof CommunicationChannel){
				CommunicationChannel cC = (CommunicationChannel)obj;
				switch(attr){
				case INIT_NODE:
					cC.setInitiatorNode(Long.parseLong(str));
					break;
				case LIST_NODE:
					cC.setListeningNode(Long.parseLong(str));
					break;
				case TRANS_PROTOCOL:
					cC.getTransportProtocol().setName(str);
					break;
				case APP_PROTOCOL:
					cC.getApplicationProtocol().setName(str);
					break;
				case INIT_PORTRANGE_START:
				{
					int range[] = cC.getInitiatorPortRange();
					range[0] = Integer.parseInt(str);
					cC.setInitiatorPortRange(range[0], range[1]);
				}
					break;
				case INIT_PORTRANGE_END:
				{
					int range[] = cC.getInitiatorPortRange();
					range[1] = Integer.parseInt(str);
					cC.setInitiatorPortRange(range[0], range[1]);
				}
					break;
				case LIST_PORTRANGE_START:
				{
					int range[] = cC.getListenerPortRange();
					range[0] = Integer.parseInt(str);
					cC.setListenerPortRange(range[0], range[1]);
				}
					break;
				case LIST_PORTRANGE_END:
				{
					int range[] = cC.getListenerPortRange();
					range[1] = Integer.parseInt(str);
					cC.setListenerPortRange(range[0], range[1]);
				}
					break;
				}
			}
		}
	}
	
	public JScrollPane getAttributesScrollPane(){
		return attributesScrollPane;
	}
}
